<?php if (!defined('DEDEINC')) {
    exit("DedeCMS Error: Request Error!");
}

/**
 * 用户登录类
 *
 * @version   $Id: userlogin.class.php 1 15:59 2010年7月5日 $
 * @package   DedeCMS.Libraries
 * @founder   IT柏拉图, https://weibo.com/itprato
 * @author    DedeCMS团队
 * @copyright Copyright (c) 2007 - 2021, 上海卓卓网络科技有限公司 (DesDev, Inc.)
 * @license   http://help.dedecms.com/usersguide/license.html
 * @link      http://www.dedecms.com
 */

// 使用缓存助手
helper('cache');
/**
 *  检查用户名的合法性
 *
 * @access public
 * @param  string $uid      用户UID
 * @param  string $msgtitle 提示标题
 * @param  string $ckhas    检查是否存在
 * @return string
 */
function CheckUserID($uid, $msgtitle = '用户名', $ckhas = true)
{
    global $cfg_mb_notallow, $cfg_mb_idmin, $cfg_md_idurl, $cfg_soft_lang, $dsql;
    if ($cfg_mb_notallow != '') {
        $nas = explode(',', $cfg_mb_notallow);
        if (in_array($uid, $nas)) {
            return $msgtitle . '为系统禁止的标识！';
        }
    }
    if ($cfg_md_idurl == 'Y' && preg_match("/[^a-z0-9]/i", $uid)) {
        return $msgtitle . '必须由英文字母或数字组成！';
    }

    if ($cfg_soft_lang == 'utf-8') {
        $ck_uid = utf82gb($uid);
    } else {
        $ck_uid = $uid;
    }

    for ($i = 0;isset($ck_uid[$i]); $i++) {
        if (ord($ck_uid[$i]) > 0x80) {
            if (isset($ck_uid[$i + 1]) && ord($ck_uid[$i + 1]) > 0x40) {
                $i++;
            } else {
                return $msgtitle . '可能含有乱码，建议你改用英文字母和数字组合！';
            }
        } else {
            if (preg_match("/[^0-9a-z@\.-]/i", $ck_uid[$i])) {
                return $msgtitle . '不能含有 [@]、[.]、[-]以外的特殊符号！';
            }
        }
    }
    if ($ckhas) {
        $row = $dsql->GetOne("SELECT * FROM `#@__member` WHERE userid LIKE '$uid' ");
        if (is_array($row)) {
            return $msgtitle . "已经存在！";
        }

    }
    return 'ok';
}

/**
 *  保存一则消息记录
 *
 * @access public
 * @param  string $mid 用户MID
 * @param  string $mid 用户ID
 * @param  string $msg 保存消息
 * @return string
 */
function PutSnsMsg($mid, $userid, $msg)
{
    global $dsql;
    $msg = addslashes($msg);
    $query = "INSERT INTO `#@__member_snsmsg`(`mid`, `userid`, `sendtime`, `msg`) VALUES('$mid', '$userid', '" . time() . "', '$msg'); ";
    $rs = $dsql->ExecuteNoneQuery($query);
    return $rs;
}

/**
 *  检查用户是否被禁言
 *
 * @return void
 */
function CheckNotAllow()
{
    global $dsql, $cfg_ml, $cfg_mb_spacesta;
    if (empty($cfg_ml->M_ID)) {
        return;
    }

    if ($cfg_ml->M_Spacesta == -2) {
        ShowMsg("你已经被禁言，请与管理员联系！", "-1");
        exit();
    } else if ($cfg_ml->M_Spacesta == -10) {
        ShowMsg("系统开启了邮件审核机制，因此你的帐号需要审核后才能发信息！", "-1");
        exit();
    } else if ($cfg_ml->M_Spacesta < 0) {
        ShowMsg('系统开启了审核机制，因此你的帐号需要管理员审核后才能发信息！', '-1');
        exit();
    }
}

function FormatUsername($username)
{
    $username = str_replace("`", "‘", $username);
    $username = str_replace("'", "‘", $username);
    $username = str_replace("\"", "“", $username);
    $username = str_replace(",", "，", $username);
    $username = str_replace("(", "（", $username);
    $username = str_replace(")", "）", $username);
    return addslashes($username);
}

/**
 * 网站用户登录类
 *
 * @package    MemberLogin
 * @subpackage DedeCMS.Libraries
 * @link       http://www.dedecms.com
 */
class MemberLogin
{
    public $M_ID;
    public $M_LoginID;
    public $M_MbType;
    public $M_Money;
    public $M_Scores;
    public $M_UserName;
    public $M_Rank;
    public $M_Face;
    public $M_LoginTime;
    public $M_KeepTime;
    public $M_Spacesta;
    public $fields;
    public $isAdmin;
    public $M_UpTime;
    public $M_ExpTime;
    public $M_HasDay;
    public $M_JoinTime;
    public $M_Honor = '';
    public $memberCache = 'memberlogin';

    //php5构造函数
    public function __construct($kptime = -1, $cache = false)
    {
        global $dsql;
        if ($kptime == -1) {
            $this->M_KeepTime = 3600 * 24 * 7;
        } else {
            $this->M_KeepTime = $kptime;
        }
        $formcache = false;
        $this->M_ID = $this->GetNum(GetCookie("DedeUserID"));
        $this->M_LoginTime = GetCookie("DedeLoginTime");
        $this->fields = array();
        $this->isAdmin = false;
        if (empty($this->M_ID)) {
            $this->ResetUser();
        } else {
            $this->M_ID = intval($this->M_ID);

            if ($cache) {
                $this->fields = GetCache($this->memberCache, $this->M_ID);
                if (empty($this->fields)) {
                    $this->fields = $dsql->GetOne("Select * From `#@__member` where mid='{$this->M_ID}' ");
                } else {
                    $formcache = true;
                }
            } else {
                $this->fields = $dsql->GetOne("Select * From `#@__member` where mid='{$this->M_ID}' ");
            }

            if (is_array($this->fields)) {


                //间隔一小时更新一次用户登录时间
                if (time() - $this->M_LoginTime > 3600) {
                    $dsql->ExecuteNoneQuery("update `#@__member` set logintime='" . time() . "',loginip='" . GetIP() . "' where mid='" . $this->fields['mid'] . "';");
                    PutCookie("DedeLoginTime", time(), $this->M_KeepTime);
                }
                $this->M_LoginID = $this->fields['userid'];
                $this->M_MbType = $this->fields['mtype'];
                $this->M_Money = $this->fields['money'];
                $this->M_UserName = FormatUsername($this->fields['uname']);
                $this->M_Scores = $this->fields['scores'];
                $this->M_Face = $this->fields['face'];
                $this->M_Rank = $this->fields['rank'];
                $this->M_Spacesta = $this->fields['spacesta'];
                $sql = "Select titles From #@__scores where integral<={$this->fields['scores']} order by integral desc";
                $scrow = $dsql->GetOne($sql);
                $this->fields['honor'] = $scrow['titles'];
                $this->M_Honor = $this->fields['honor'];
                if ($this->fields['matt'] == 10) {
                    $this->isAdmin = true;
                }

                $this->M_UpTime = $this->fields['uptime'];
                $this->M_ExpTime = $this->fields['exptime'];
                $this->M_JoinTime = MyDate('Y-m-d', $this->fields['jointime']);
                if ($this->M_Rank > 10 && $this->M_UpTime > 0) {
                    $this->M_HasDay = $this->Judgemember();
                }
                if (!$formcache) {
                    SetCache($this->memberCache, $this->M_ID, $this->fields, 1800);
                }
            } else {
                $this->ResetUser();
            }
        }
    }

    public function MemberLogin($kptime = -1)
    {
        $this->__construct($kptime);
    }

    /**
     *  删除缓存,每次登录时和在修改用户资料的地方会清除
     *
     * @access public
     * @param  string
     * @return string
     */
    public function DelCache($mid)
    {
        DelCache($this->memberCache, $mid);
    }

    /**
     *  判断用户是否到期
     *
     * @return string
     */
    public function Judgemember()
    {
        global $dsql, $cfg_mb_rank;
        $nowtime = time();
        $mhasDay = $this->M_ExpTime - ceil(($nowtime - $this->M_UpTime) / 3600 / 24) + 1;
        if ($mhasDay <= 0) {
            $dsql->ExecuteNoneQuery(
                "UPDATE `#@__member` SET uptime='0',exptime='0',
                                         rank='$cfg_mb_rank' WHERE mid='" . $this->fields['mid'] . "';"
            );
        }
        return $mhasDay;
    }

    /**
     *  退出cookie的会话
     *
     * @return void
     */
    public function ExitCookie()
    {
        $this->ResetUser();
    }

    /**
     *  验证用户是否已经登录
     *
     * @return bool
     */
    public function IsLogin()
    {
        if ($this->M_ID > 0) {
            return true;
        } else {
            return false;
        }

    }

    /**
     *  检测用户上传空间
     *
     * @return int
     */
    public function GetUserSpace()
    {
        global $dsql;
        $uid = $this->M_ID;
        $row = $dsql->GetOne("SELECT sum(filesize) AS fs FROM `#@__uploads` WHERE mid='$uid'; ");
        return $row['fs'];
    }

    /**
     *  检查用户空间信息
     *
     * @return void
     */
    public function CheckUserSpace()
    {
        global $cfg_mb_max;
        $uid = $this->M_ID;
        $hasuse = $this->GetUserSpace();
        $maxSize = $cfg_mb_max * 1024 * 1024;
        if ($hasuse >= $maxSize) {
            ShowMsg('你的空间已满，不允许上传新文件！', '-1');
            exit();
        }
    }

    /**
     *  更新用户信息统计表
     *
     * @access public
     * @param  string $field  字段信息
     * @param  string $uptype 更新类型
     * @return string
     */
    public function UpdateUserTj($field, $uptype = 'add')
    {
        global $dsql;
        $mid = $this->M_ID;
        $arr = $dsql->GetOne("Select * `#@__member_tj` where mid='$mid' ");
        if (!is_array($arr)) {
            $arr = array('article' => 0, 'album' => 0, 'archives' => 0, 'homecount' => 0, 'pagecount' => 0, 'feedback' => 0, 'friend' => 0, 'stow' => 0);
        }
        extract($arr);
        if (isset($$field)) {
            if ($uptype == 'add') {
                $$field++;
            } else if ($$field > 0) {
                $$field--;
            }
        }
        $inquery = "INSERT INTO `#@__member_tj` (`mid`,`article`,`album`,`archives`,`homecount`,`pagecount`,`feedback`,`friend`,`stow`)
               VALUES ('$mid','$article','$album','$archives','$homecount','$pagecount','$feedback','$friend','$stow'); ";
        $dsql->ExecuteNoneQuery("Delete From `#@__member_tj` where mid='$mid' ");
        $dsql->ExecuteNoneQuery($inquery);
    }

    //
    /**
     *  重置用户信息
     *
     * @return void
     */
    public function ResetUser()
    {
        $this->fields = '';
        $this->M_ID = 0;
        $this->M_LoginID = '';
        $this->M_Rank = 0;
        $this->M_Face = "";
        $this->M_Money = 0;
        $this->M_UserName = "";
        $this->M_LoginTime = 0;
        $this->M_MbType = '';
        $this->M_Scores = 0;
        $this->M_Spacesta = -2;
        $this->M_UpTime = 0;
        $this->M_ExpTime = 0;
        $this->M_JoinTime = 0;
        $this->M_HasDay = 0;
        DropCookie('DedeUserID');
        DropCookie('DedeLoginTime');
    }

    /**
     *  获取整数值
     *
     * @access public
     * @param  string $fnum 处理的数值
     * @return string
     */
    public function GetNum($fnum)
    {
        $fnum = preg_replace("/[^0-9\.]/", '', $fnum);
        return $fnum;
    }

    /**
     *  用户登录
     *  把登录密码转为指定长度md5数据
     *
     * @access public
     * @param  string $pwd 需要加密的密码
     * @return string
     */
    public function GetEncodePwd($pwd)
    {
        global $cfg_mb_pwdtype;
        if (empty($cfg_mb_pwdtype)) {
            $cfg_mb_pwdtype = '32';
        }

        switch ($cfg_mb_pwdtype) {
        case 'l16':
            return substr(md5($pwd), 0, 16);
        case 'r16':
            return substr(md5($pwd), 16, 16);
        case 'm16':
            return substr(md5($pwd), 8, 16);
        default:
            return md5($pwd);
        }
    }

    /**
     *  把数据库密码转为特定长度
     *  如果数据库密码是明文的，本程序不支持
     *
     * @access public
     * @param  string
     * @return string
     */
    public function GetShortPwd($dbpwd)
    {
        global $cfg_mb_pwdtype;
        if (empty($cfg_mb_pwdtype)) {
            $cfg_mb_pwdtype = '32';
        }

        $dbpwd = trim($dbpwd);
        if (strlen($dbpwd) == 16) {
            return $dbpwd;
        } else {
            switch ($cfg_mb_pwdtype) {
            case 'l16':
                return substr($dbpwd, 0, 16);
            case 'r16':
                return substr($dbpwd, 16, 16);
            case 'm16':
                return substr($dbpwd, 8, 16);
            default:
                return $dbpwd;
            }
        }
    }

    /**
     *  检查用户是否合法
     *
     * @access public
     * @param  string $loginuser 登录用户名
     * @param  string $loginpwd  用户密码
     * @return string
     */
    public function CheckUser(&$loginuser, $loginpwd)
    {
        global $dsql;

        //检测用户名的合法性
        $rs = CheckUserID($loginuser, '用户名', false);

        //用户名不正确时返回验证错误，原登录名通过引用返回错误提示信息
        if ($rs != 'ok') {
            $loginuser = $rs;
            return '0';
        }

        //matt=10 是管理员关连的前台帐号，为了安全起见，这个帐号只能从后台登录，不能直接从前台登录
        $row = $dsql->GetOne("SELECT mid,matt,pwd,logintime FROM `#@__member` WHERE userid LIKE '$loginuser' ");
        if (is_array($row)) {
            if ($this->GetShortPwd($row['pwd']) != $this->GetEncodePwd($loginpwd)) {
                return -1;
            } else {
                //管理员帐号不允许从前台登录
                if ($row['matt'] == 10) {
                    return -2;
                } else {
                    $this->PutLoginInfo($row['mid'], $row['logintime']);
                    return 1;
                }
            }
        } else {
            return 0;
        }
    }

    /**
     *  保存用户cookie
     *
     * @access public
     * @param  string $uid       用户ID
     * @param  string $logintime 登录限制时间
     * @return void
     */
    public function PutLoginInfo($uid, $logintime = 0)
    {
        global $cfg_login_adds, $dsql;
        //登录增加积分(上一次登录时间必须大于两小时)
        if (time() - $logintime > 7200 && $cfg_login_adds > 0) {
            $dsql->ExecuteNoneQuery("Update `#@__member` set `scores`=`scores`+{$cfg_login_adds} where mid='$uid' ");
        }
        $this->M_ID = $uid;
        $this->M_LoginTime = time();
        $loginip = GetIP();
        $inquery = "UPDATE `#@__member` SET loginip='$loginip',logintime='" . $this->M_LoginTime . "' WHERE mid='" . $uid . "'";
        $dsql->ExecuteNoneQuery($inquery);
        if ($this->M_KeepTime > 0) {
            PutCookie('DedeUserID', $uid, $this->M_KeepTime);
            PutCookie('DedeLoginTime', $this->M_LoginTime, $this->M_KeepTime);
        } else {
            PutCookie('DedeUserID', $uid);
            PutCookie('DedeLoginTime', $this->M_LoginTime);
        }
    }

    /**
     *  获得用户目前的状态
     *
     * @access public
     * @param  string $dsql 数据库连接
     * @return string
     */
    public function GetSta($dsql)
    {
        $sta = '';
        if ($this->M_Rank == 0) {
            $sta .= "你目前的身份是：普通用户";
        } else {
            $row = $dsql->GetOne("Select membername From `#@__arcrank` where rank='" . $this->M_Rank . "'");
            $sta .= "你目前的身份是：" . $row['membername'];
            $rs = $dsql->GetOne("Select id From `#@__admin` where userid='" . $this->M_LoginID . "'");
            if (!is_array($rs)) {
                if ($this->M_Rank > 10 && $this->M_HasDay > 0) {
                    $sta .= " 剩余天数: <font color='red'>" . $this->M_HasDay . "</font>  天 ";
                } elseif ($this->M_Rank > 10) {
                    $sta .= " <font color='red'>用户升级已经到期</font> ";
                }

            }
        }
        $sta .= " 拥有金币：{$this->M_Money} 个， 积分：{$this->M_Scores} 分。";
        return $sta;
    }

    /**
     *  记录用户操作日志
     *
     * @access public
     * @param  string $type                       记录类型
     * @param  string $title                      记录标题
     * @param  string $note记录描述
     * @param  string $aid涉及到的内容的id
     * @return string
     */
    public function RecordFeeds($type, $title, $note, $aid)
    {
        global $dsql, $cfg_mb_feedcheck;
        //确定是否需要记录
        if (in_array($type, array('add', 'addsoft', 'feedback', 'addfriends', 'stow'))) {
            $ntime = time();
            $title = dede_htmlspecialchars(cn_substrR($title, 255));
            if (in_array($type, array('add', 'addsoft', 'feedback', 'stow'))) {
                $rcdtype = array('add' => ' 成功发布了', 'addsoft' => ' 成功发布了软件',
                    'feedback' => ' 评论了文章', 'stow' => ' 收藏了');
                //内容发布处理
                $arcrul = " <a href='/plus/view.php?aid=" . $aid . "'>" . $title . "</a>";
                $title = dede_htmlspecialchars($rcdtype[$type] . $arcrul, ENT_QUOTES);
            } else if ($type == 'addfriends') {
                //添加好友处理
                $arcrul = " <a href='/member/index.php?uid=" . $aid . "'>" . $aid . "</a>";
                $title = dede_htmlspecialchars(' 与' . $arcrul . "成为好友", ENT_QUOTES);
            }
            $note = Html2Text($note);
            $aid = (isset($aid) && is_numeric($aid) ? $aid : 0);
            $ischeck = ($cfg_mb_feedcheck == 'Y') ? 0 : 1;
            $query = "INSERT INTO `#@__member_feed` (`mid`, `userid`, `uname`, `type`, `aid`, `dtime`,`title`, `note`, `ischeck`)
                        Values('$this->M_ID', '$this->M_LoginID', '$this->M_UserName', '$type', '$aid', '$ntime', '$title', '$note', '$ischeck'); ";
            $rs = $dsql->ExecuteNoneQuery($query);
            return $rs;
        } else {
            return false;
        }
    }
} //End Class
